home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / QuickDraw™ GX / Programming Stuff / Sample Code / Typography Samples / Adjust Layout ƒ / Adjust Layout.c next >
Encoding:
C/C++ Source or Header  |  1995-04-10  |  16.4 KB  |  497 lines  |  [TEXT/KAHL]

  1. /**\
  2. |**| =====================================================================
  3. |**|
  4. |**|    Adjust Layout.c
  5. |**|
  6. |**|    This file contains the calls that this sample needs to make
  7. |**|    the QuickDraw GX shell work correctly.
  8. |**|
  9. |**|    QuickDraw GX Libraries Used:
  10. |**|    "color library.c", "font library.c", "graphics debug library.c",
  11. |**|    "layout library.c", "shape library.c", and "transform library.c".
  12. |**|
  13. |**|    ©1992-1994  Apple Computer, Inc.
  14. |**|    All rights reserved.
  15. |**|
  16. |**| =====================================================================
  17. \**/
  18.  
  19.  
  20. #include "QDGX shell.h"
  21. #include "layout routines.h"
  22. #include "layout library.h"
  23.  
  24.  
  25. // Convenient constants for simplifying the code
  26.  
  27. #define withFactor {0, -ff(4)/30}
  28. #define crossFactor {0, fixed1/3}
  29. #define glyphA 36
  30. #define glyphE (glyphA + 'E' - 'A')
  31. #define glyphJ (glyphA + 'J' - 'A')
  32. #define glyphK (glyphA + 'K' - 'A')
  33. #define glyphN (glyphA + 'N' - 'A')
  34. #define glyphU (glyphA + 'U' - 'A')
  35. #define glyphV (glyphA + 'V' - 'A')
  36. #define glyphW (glyphA + 'W' - 'A')
  37. #define glyphY (glyphW + 2)
  38. #define nAdjustments 3
  39. #define nSubstitutions 4
  40.  
  41.  
  42. /**\
  43. |**| ---------------------------------------------------------------------
  44. |**| PROTOTYPES
  45. |**| ---------------------------------------------------------------------
  46. \**/
  47.  
  48. // funtions required by shell
  49.  
  50. void    DoSetup            (void);
  51. void    DoDraw            (WindowPtr wind, Boolean updating);
  52. OSErr    DoCreateNew        (void);
  53. void    DoDispose        (WindowPtr wind);
  54. void    DoIdle            (WindowPtr wind);
  55. void    DoTeardown        (void);
  56. void    DoClick            (WindowPtr wind, Point p);
  57.  
  58. // private functions
  59.  
  60. OSErr    DoWindowInit        (WindowPtr wind);
  61. void    CreateSampleImage    (WindowPtr wind);
  62.  
  63.  
  64. /**\
  65. |**| ---------------------------------------------------------------------
  66. |**| ENUMS
  67. |**| ---------------------------------------------------------------------
  68. \**/
  69. enum { rWindResource = 128 };
  70.  
  71.  
  72. /**\
  73. |**| ---------------------------------------------------------------------
  74. |**| GLOBALS
  75. |**| ---------------------------------------------------------------------
  76. \**/
  77. // If gDebugging = TRUE, graphics library errors and notices will be posted.  This
  78. // functionality will only work with the "debugging" version of QuickDraw GX.
  79. // If the debugging version is not installed, nothing bad will happen, but these
  80. // functions will not work. 
  81.  
  82. Boolean        gDebugging = true;
  83.  
  84. // Set  "gGiveMeValidation" to TRUE if you want receive run-time validation.
  85.  
  86. Boolean        gGiveMeValidation = true;
  87.  
  88.  
  89. // gGraphicsHeapSize sets the size of the graphics heap created by calling the
  90. // GXNewGraphicsClient routine in main () within QuickDraw GX shell.c.  You can determine
  91. // the amount of graphics heap required by using GraphicsBug.  I'm giving it 600K,
  92. // since we need abunch if we have several windows open.
  93.  
  94. long        gGraphicsHeapSize = 600;
  95.  
  96. // gOurPrintingOverrideUPP is a universal proc pointer for our printing event
  97. // override.  This is so that our override can be native PowerPC code if necessary.
  98.  
  99. GXPrintingEventUPP    gOurPrintingOverrideUPP;
  100.  
  101.  
  102.  
  103. /**\
  104. |**| ---------------------------------------------------------------------
  105. |**| DoSetup()
  106. |**| Here's where we initialize any global variables our application needs.
  107. |**| We have only one at this time -- the universal proc pointer for
  108. |**| our printing override.
  109. |**| ---------------------------------------------------------------------
  110. \**/
  111. void DoSetup (void)
  112. {    // Initialize our printing event override UPP
  113.     gOurPrintingOverrideUPP = NewGXPrintingEventProc(MyPrintingEventOverride);
  114. }
  115.  
  116.  
  117. /**\
  118. |**| ---------------------------------------------------------------------
  119. |**| DoDraw()
  120. |**| Draw the contents of the window.  The first parameter is the window
  121. |**| to draw, and the second parameter is true if we're updating an existing
  122. |**| image.  If that's the case, we don't want to change anything, but
  123. |**| just draw what's already there.
  124. |**| ---------------------------------------------------------------------
  125. \**/
  126. void DoDraw (WindowPtr wind, Boolean updating)
  127. {
  128.      #pragma unused (updating)
  129.      GXDrawShape (GetDocShape(wind));
  130. }
  131.  
  132.  
  133. /**\
  134. |**| ---------------------------------------------------------------------
  135. |**| DoCreateNew()
  136. |**| This routine is called when a window needs to be created.
  137. |**| ---------------------------------------------------------------------
  138. \**/
  139. OSErr DoCreateNew (void)
  140. {
  141.     OSErr        err = noErr;
  142.     WindowPtr    wind;
  143.     
  144. // Get and create our window from the resource fork
  145.  
  146.     wind = GetNewWindow(rWindResource, nil, (WindowPtr)-1L);
  147.  
  148. // Attach a default gxViewPort to it, create and iInitialize our
  149. // private data for it, and add a sample image to its page shape.
  150.  
  151.     if ( wind == NULL )
  152.         return (MemError());
  153.  
  154.     GXIgnoreGraphicsNotice(transform_already_set);
  155.     SetDefaultViewPort(GXNewWindowViewPort(wind));            
  156.     GXPopGraphicsNotice();
  157.     
  158.     err = DoWindowInit(wind);
  159.     if ( err != noErr )
  160.         return err;
  161.     
  162.     CreateSampleImage(wind);
  163.     return err;
  164. }
  165.  
  166.  
  167. /**\
  168. |**| ---------------------------------------------------------------------
  169. |**| DoDispose()
  170. |**| This routine is called when a window needs to be disposed of.
  171. |**| ---------------------------------------------------------------------
  172. \**/
  173. void DoDispose (WindowPtr wind)
  174. {
  175.     TH_Doc    doc;
  176.     
  177. // You should always dispose of your GX graphics objects before tossing your window.
  178. // Why?  It's generally good form and this approach guarantees that everything is
  179. // disposed.  If you had not disposed of everything, the call to DisposeWindow should
  180. // dispose of the objects. If you are running the debugging version of QuickDraw GX
  181. // with notices set, you will receive a notice that you had not disposed of everything.
  182. // You can turn notices on in this file by setting gDebugging = TRUE (above).
  183.     
  184.     if ( wind != NULL )
  185.     {
  186.         doc = (TH_Doc)GetWRefCon(wind);        // Remember, this is where we stored our private data.
  187.         GXDisposeShape(GetDocShape(wind));     // Dispose of this doc's shape.
  188.         GXDisposeJob(GetDocJob(wind));        // Dispose of this doc's print job.
  189.         DisposHandle((Handle) doc);            // Dispose of our private data.
  190.         DisposeWindow(wind);                // Dispose of the window.
  191.     }
  192. }
  193.  
  194.  
  195. /**\
  196. |**| ---------------------------------------------------------------------
  197. |**| DoIdle()
  198. |**| This routine is called to do things while idling through the event loop.
  199. |**| ---------------------------------------------------------------------
  200. \**/
  201. void DoIdle (WindowPtr wind)
  202. {
  203. }
  204.  
  205.  
  206. /**\
  207. |**| ---------------------------------------------------------------------
  208. |**| DoTeardown()
  209. |**| This routine is called just before we quit to remove anything 
  210. |**| persistent that might have been setup by DoSetup().
  211. |**| ---------------------------------------------------------------------
  212. \**/
  213. void DoTeardown (void)
  214. {
  215.     DisposeRoutineDescriptor(gOurPrintingOverrideUPP);
  216. }
  217.  
  218.  
  219. /**\
  220. |**| ---------------------------------------------------------------------
  221. |**| DoClick()
  222. |**| ---------------------------------------------------------------------
  223. \**/
  224. void DoClick(WindowPtr window, Point p)
  225. {
  226. }
  227.  
  228.  
  229.  
  230.  
  231.  
  232. /**\
  233. |**| ---------------------------------------------------------------------
  234. |**| DoWindowInit()
  235. |**| In this function we create and initialize the the private document
  236. |**| structure for a new window.  This structure contains the print job and
  237. |**| the shape which is drawn in the window.  We store this data in a handle
  238. |**| and hang it off the window's refCon field for easy retrieval.  By doing
  239. |**| this, rather than using globals, we can create many windows containing
  240. |**| unique print jobs and shapes.
  241. |**| ---------------------------------------------------------------------
  242. \**/
  243. OSErr DoWindowInit (WindowPtr wind)
  244. {
  245.     OSErr    err = noErr;
  246.     gxJob    docJob;
  247.     gxShape    docPage;
  248.     TH_Doc    windDoc;
  249.  
  250.  
  251. // Create the page shape. We set the unique items attribute to make sure that each item
  252. // added to the picture has a unique reference. If this attribute was not set, we would
  253. // not see all copies of anything we add to the shape multiple times -- we'd just see
  254. // the last version added.        
  255.  
  256.     docPage = GXNewShape(gxPictureType);
  257.     GXSetShapeAttributes(docPage, (GXGetShapeAttributes(docPage) | gxUniqueItemsShape));
  258.     
  259.     
  260. // Create a print job for this document.  This will be the same as the system default until
  261. // the user goes through the dialogs for Page Setup or Print…
  262.  
  263.     err = GXNewJob(&docJob);
  264.     
  265.     
  266. // If there are no errors, create a handle the size of our document structure and store
  267. // the print job and page shape in it.  Store the handle in the window's refCon field so
  268. // that we can get at it.  (Note that the utility routines "GetDocJob" and "GetDocShape"
  269. // can be used to do this easily.
  270.  
  271.     if ( err == noErr )
  272.     {
  273.         windDoc = (TH_Doc) NewHandleClear(sizeof(T_Doc));
  274.  
  275.         if ( windDoc == NULL )
  276.             err = MemError();
  277.         else
  278.         {
  279.             (*windDoc)->docJob = docJob;
  280.             (*windDoc)->docPage = docPage;
  281.             SetWRefCon(wind, (long) windDoc);
  282.         }
  283.  
  284. // Now install our application override for PrintingEvent so that we can
  285. // support the new movable-modal printing dialog boxes.
  286.  
  287.         GXInstallApplicationOverride(docJob, gxPrintingEvent, gOurPrintingOverrideUPP);
  288.  
  289.     }
  290.  
  291.     return err;
  292. }
  293.  
  294.  
  295. /**\
  296. |**| ---------------------------------------------------------------------
  297. |**| CreateSampleImage()
  298. |**| This function creates primitive shapes and adds them to the window's page shape.
  299. |**| ---------------------------------------------------------------------
  300. \**/
  301. void CreateSampleImage (WindowPtr wind)
  302. {
  303.     Rect    ourWindowRect = wind->portRect;         // the rectangle for this window
  304.                                                     // in QuickDraw coordinates
  305.     gxShape layout;                                    // the layout shape we're building
  306.     gxShape thePage;                                // the picture shape for our window
  307.     gxRunControls controls;                            // run controls for the layout
  308.     gxLayoutOptions layoutOptions;                    // options for our layout
  309.     StyleRunOverrides overrides;                    // structure defined in layout library.h
  310.                                                     // and used in several library calls to
  311.                                                     // make working with style runs easier
  312.     gxStyle glyphStyles[3];                            // array of three different styles for
  313.                                                     // glyphs we use
  314.     // Here's the text of the three runs
  315.     
  316.     char *text1 = "Office";
  317.     char *text2 = "AWAY AND SOME ";
  318.     char *text3 = "JUNK.";
  319.     
  320.     char *textRuns[3];                                // and the array to hold them
  321.     
  322.     short level0 = 0;                                // We have to pass levels by address,
  323.                                                     // so here's a variable to hold one            
  324.     short textLengths[3];                            // array of text lengths for GXNewLayout
  325.     short totalLength;                                // sum of the text lengths
  326.     
  327. // The "glyphX" values are #define'd at the top of this file.  There are four
  328. // values in each set -- the glyph code of the first glyph, the glyph code of the
  329. // second glyph, how much with-stream kerning to apply and how much cross-stream
  330. // kerning to apply.  We're kerning with the pairs A-W, A-Y and W-A here.
  331. // Normally you would _not_ hard-code glyph codes because they can change from font
  332. // to font, but this is a demonstration, not a shipping application.  Try this on
  333. // some non-Roman fonts, or some where the glyph codes for the ASCII characters aren't
  334. // the same as their ASCII value, and you'll see strange results.
  335.     
  336.     gxKerningAdjustment adjustments[nAdjustments] = 
  337.     {{glyphA, glyphW, withFactor, crossFactor}, 
  338.      {glyphA, glyphY, withFactor, crossFactor}, 
  339.      {glyphW, glyphA, withFactor, crossFactor}};
  340.      
  341. // The gxGlyphSubstitution array lets us substitute one glyph for another by
  342. // glyph code.  Again taking the liberty of assuming glyph codes for Times Roman,
  343. // this set substitutes the second glyph in each pair for the first when the layout
  344. // shape is drawn.
  345.      
  346.     gxGlyphSubstitution substitutions[nSubstitutions] = 
  347.     {{glyphJ, glyphW},
  348.      {glyphU, glyphA},
  349.      {glyphN, glyphV},
  350.      {glyphK, glyphE}};
  351.     
  352.     gxPoint posn;                                    // The position for the layout shape
  353.  
  354.     
  355. // OK, now to work.  First, initialize the textRuns array.
  356.  
  357.     textRuns[0] = text1;
  358.     textRuns[1] = text2;
  359.     textRuns[2] = text3;
  360.     
  361.     
  362. // Next, initialize the textLengths array.  MyStrLength is in this file to avoid linking
  363. // in a huge ANSI library.
  364.     
  365.     textLengths[0] = MyStrLength (text1);
  366.     textLengths[1] = MyStrLength (text2);
  367.     textLengths[2] = MyStrLength (text3);
  368.     
  369.     
  370. // Now add them all up to get the total length.
  371.     
  372.     totalLength = textLengths[0] + textLengths[1] + textLengths[2];
  373.     
  374.     
  375. // Make default gxLayoutOptions, gxRunControls and StyleRunOverrides structures.
  376. // The library routines which initialize these default structures may be found in
  377. // layout library.c.
  378.     
  379.     InitializeLayoutOptions (&layoutOptions);
  380.     InitializeRunControls (&controls);
  381.     InitializeStyleRunOverrides (&overrides);
  382.     
  383. // Position the layout half way down the left edge of the window. Set 
  384. // the layout's width to the window's width and set the flushness to 1/2, this
  385. // will cause the layout to center in the window.
  386.  
  387.     layoutOptions.width = ff(ourWindowRect.right - ourWindowRect.left);
  388.     layoutOptions.flush = fract1/2;        // fract1 is defined in math types.h
  389.  
  390.     posn.x = 0;
  391.     posn.y = ff((ourWindowRect.bottom - ourWindowRect.top) / 2);
  392.  
  393.     
  394. // Initialize the style runs.  The first one (#0) is 60 point Times Roman.
  395. // We create the style with NewLayoutStyle, found in layout library.c
  396.  
  397.     glyphStyles[0] = NewLayoutStyle(
  398.         (char *) "\pHoefler Text",    // The gxFontName for this style
  399.         ff(60),                        // the text size in fixed point
  400.         0,                            // gxTextAttribute (none for us)
  401.         &controls,                    // run controls (none for this style)
  402.         nil,                        // run features (none right now)
  403.         0,                            // count of run features (no run features == 0)
  404.         nil);                        // style run overrides (none right now)
  405.  
  406. // Now we create the next style.  We reuse the controls and style run overrides
  407. // structures, so now we set those up for the second (#1) style.
  408.  
  409. // Initialize the run controls:
  410. // Set the cross stream shift to 30 to raise the text 30 points,
  411. // and the with stream shift to -4 to move the text 4 points
  412. // closer together than normal kerning would move it.
  413.  
  414.     controls.crossStreamShift = ff(30);
  415.     controls.beforeWithStreamShift = ff(-2);
  416.     controls.afterWithStreamShift = ff(-2);
  417.  
  418. // Now set up the style run overrides:
  419. // Set up the kerning adjustments to the array we already created, and
  420. // put the count in.  nAdjustments is #define'd in Adjust Layout Sample.h.
  421.     
  422.     overrides.kerningAdjustments = adjustments;
  423.     overrides.kerningAdjustmentsCount = nAdjustments;
  424.  
  425. // We're ready to create the second style -- 30 pt. Times Roman with kerning adjustments
  426.     
  427.     glyphStyles[1] = NewLayoutStyle(
  428.         (char *) "\pTimes Roman",    // the gxFontName
  429.         ff(30),                        // the text size
  430.         0,                            // no text attributes
  431.         &controls,                    // our run controls we initialized
  432.         nil,                        // no run features
  433.         0,                            // so the run feature count is zero
  434.         &overrides);                // and our style run overrides (kerning adjustments)
  435.     
  436. // For the third style, we reset the run controls and kerning adjustments, but now
  437. // set the glyph substitutions talked about earlier.
  438.  
  439.     controls.crossStreamShift = 0;                            // default
  440.  
  441.     overrides.kerningAdjustments = nil;                        // default
  442.     overrides.kerningAdjustmentsCount = 0;                    // default
  443.  
  444.     overrides.glyphSubstitutions = substitutions;            // our glyph subs array
  445.     overrides.glyphSubstitutionsCount = nSubstitutions;        // our glyph subs count
  446.     
  447.     
  448. // Finally, create the third style -- 60 pt. Times Roman with glyph substitutions
  449.  
  450.     glyphStyles[2] = NewLayoutStyle(
  451.         (char *) "\pTimes Roman",    // the font name
  452.         ff(60),                        // the text size
  453.         0,                            // no text attributes
  454.         &controls,                    // our run controls (default again)
  455.         nil,                        // no run features
  456.         0,                            // so the run feature count is zero
  457.         &overrides);                // and our style run overrides (glyph subs)
  458.  
  459. // Now we can build the layout and add it to our picture shape
  460.     
  461.     layout = GXNewLayout(
  462.         3,                            // count of text runs
  463.         textLengths,                // array of lengths of each run
  464.         (void *) textRuns,            // array of pointers to the text
  465.         3,                            // count of style runs
  466.         textLengths,                // array of the byte length of each style run
  467.         glyphStyles,                // the array of styles we've been constructing
  468.         1,                            // the number of levels in this layout
  469.         &totalLength,                // the length of text this level applies to (all of it)
  470.         &level0,                    // array of next levels (this could be nil, too)
  471.         &layoutOptions,                // our layout options (centered, flush 1/2, etc.)
  472.         &posn);                        // the position of the layout shape
  473.         
  474.  
  475. // Retrieve the page shape so we can add to it.
  476.  
  477.     thePage = GetDocShape(wind);
  478.     
  479. // Add the layout to the window's picture shape.  AddToShape is in shape library.c.
  480.  
  481.     AddToShape(thePage, layout);
  482.     
  483. // We're done with the layout and styles, so get rid of them
  484.  
  485.     GXDisposeShape(layout);
  486.     GXDisposeStyle(glyphStyles[0]);
  487.     GXDisposeStyle(glyphStyles[1]);
  488.     GXDisposeStyle(glyphStyles[2]);
  489.     
  490.     
  491. // Invalidate the window's portRect so that everything gets updated.
  492.     
  493.     SetPort(wind);
  494.     InvalRect(&ourWindowRect);
  495. }
  496.  
  497.